
#ifndef TOKZRGENTR_PARSING_SYNTAX_TREES_H
#define TOKZRGENTR_PARSING_SYNTAX_TREES_H

#include"ivisitors.h"
#include"ucs2_ranges.h"
#include<memory>
#include"u16string_ref.h"
//#	tokenizer generator script format file(.tgs)
//#	using difference syntax tree node for regex and .tgs parsing syntax tree

namespace TokzrGentr
{
	//#	node class for syntax tree
	using syntax_node = class syntax_node;
	using regex = class regex;
	using decl = class decl;
	using token_identifier = class token_identifier;
	using stmt = class stmt;
	using stmts = class stmts;

	using regex_node = class regex_node;
	using char_set = class char_set;
	using binary_op_node = class binary_op_node;
	using cater_node = class cater_node;
	using alter_node = class alter_node;
	using repeat_node = class repeat_node;

	class syntax_node 
	{
	public:
		~syntax_node(){}
		virtual void accept(syntax_node_ivisitor *visitor) = 0;
	};


	//#	node for regex
	class regex : public syntax_node
	{
	private:
		std::u16string _regex_str;
	public:
		regex(const std::u16string &str)
			:_regex_str(str){}
		void accept(syntax_node_ivisitor *visitor) override
		{
			visitor->visit(this);
		}
		std::u16string regex_str() const
		{
			return _regex_str;
		}
	};
	
	class token_identifier : public syntax_node
	{
	private:
		std::u16string _name;
	public:
		token_identifier(const std::u16string &nm)
			:_name(nm) {}
		void accept(syntax_node_ivisitor *visitor) override
		{
			visitor->visit(this);
		}
		std::u16string Name() const
		{
			return _name;
		}
	};

	class decl : public syntax_node
	{
	private:
		std::shared_ptr<token_identifier> _identifier;
		std::shared_ptr<regex> _regex;
	public:
		decl(
			std::shared_ptr<token_identifier> idfer,
			std::shared_ptr<regex> re
		)
			:_identifier(idfer), _regex(re) {}
		void accept(syntax_node_ivisitor *visitor) override
		{
			visitor->visit(this);
		}

		std::shared_ptr<token_identifier> identifier()
		{
			return _identifier;
		}

		std::shared_ptr<regex> regex()
		{
			return _regex;
		}
	};

	class stmt : public syntax_node
	{
	private:
		std::shared_ptr<decl> _decl;
		size_t _rank;
	public:
		stmt(
			std::shared_ptr<decl> dcl,
			size_t r
		)
			:_decl(dcl), _rank(r) {}
		size_t rank() const
		{
			return _rank;
		}
		std::shared_ptr<decl> decl()
		{
			return _decl;
		}
		void accept(syntax_node_ivisitor *visitor) override
		{
			visitor->visit(this);
		}
	};

	class stmts : public syntax_node
	{
	private:
		std::vector<std::shared_ptr<stmt>> _stmts;
	public:
		stmts(){}
		void add_stmt(std::shared_ptr<stmt> statement)
		{
			_stmts.push_back(statement);
		}
		
		std::vector<std::shared_ptr<stmt>> all_stmts()
		{
			return _stmts;
		}
		void accept(syntax_node_ivisitor *visitor) override
		{
			visitor->visit(this);
		}
	};

	class root : public syntax_node
	{
	private:
		std::u16string _tokzr_name;
		std::shared_ptr<stmts> _stmts;
	public:
		root(
			const std::u16string &name,
			const std::shared_ptr<stmts> stmt_list
		)
			:_tokzr_name(name), _stmts(stmt_list) {}

		std::u16string TokzrName() const
		{
			return _tokzr_name;
		}
		std::shared_ptr<stmts> stmts() const
		{
			return _stmts;
		}

		void accept(syntax_node_ivisitor *visitor) override
		{
			visitor->visit(this);
		}
	};

	class regex_node
	{
	public:
		virtual ~regex_node() {};
		virtual void accept(regex_node_ivisitor *visitor) = 0;
	};

	class char_set_node : public regex_node
	{
	private:
		std::shared_ptr<ucs2_ranges_set> _ucs_sets;
	public:
		char_set_node(std::shared_ptr<ucs2_ranges_set> ucs_sets)
			:_ucs_sets(ucs_sets) {}
		void accept(regex_node_ivisitor *visitor) override
		{
			visitor->visit(this);
		}
		std::shared_ptr<ucs2_ranges_set> ucs_sets()
		{
			return _ucs_sets;
		}
	};

	class binary_op_node : public regex_node
	{
	private:
		std::shared_ptr<regex_node> _lhs;
		std::shared_ptr<regex_node> _rhs;
	public:
		binary_op_node(
			std::shared_ptr<regex_node> l,
			std::shared_ptr<regex_node> r
		) 
			:_lhs(l), _rhs(r) {}
		virtual ~binary_op_node() override{};
		std::shared_ptr<regex_node> lhs()
		{
			return _lhs;
		}
		std::shared_ptr<regex_node> rhs()
		{
			return _rhs;
		}
		virtual void accept(regex_node_ivisitor *visitor) override = 0;
	};

	class cater_node : public binary_op_node
	{
	public:
		cater_node(
			std::shared_ptr<regex_node> l,
			std::shared_ptr<regex_node> r
		)
			:binary_op_node(l, r) {}
		
		void accept(regex_node_ivisitor *visitor) override
		{
			visitor->visit(this);
		}
	};

	class alter_node : public binary_op_node
	{
	public:
		alter_node(
			std::shared_ptr<regex_node> l,
			std::shared_ptr<regex_node> r
		)
			:binary_op_node(l, r) {}

		void accept(regex_node_ivisitor *visitor) override
		{
			visitor->visit(this);
		}
	};


	//#	+ -> {1,0,false}
	//#	* -> {0,0,false}
	//# ? -> {0,1,true}
	//#	{n} -> {n,n,true}
	//#	{n,m} -> {n,m,true}
	//#	{,m} ->{0,m,true}
	//#	{n,} ->{n,0,false}
	class repeat_node : public regex_node
	{
	private:
		std::shared_ptr<regex_node> _operand;
		size_t _min_times;
		size_t _max_times;
		bool _is_finited;
	public:
		repeat_node(
			std::shared_ptr<regex_node> op,
			size_t min,
			size_t max,
			bool finited
		)
			:_operand(op), _min_times(min), _max_times(max),_is_finited(finited) {}

		bool is_finited()
		{
			return _is_finited;
		}
		void accept(regex_node_ivisitor *visitor) override
		{
			visitor->visit(this);
		}
		size_t min_times() 
		{
			return _min_times;
		}
		size_t max_times()
		{
			return _max_times;
		}
		std::shared_ptr<regex_node> operand()
		{
			return _operand;
		}
	};
}

#endif // !TOKZRGENTR_PARSING_SYNTAX_TREES_H
